package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import idv.cjcat.stardust.common.emitters.Emitter;
	import idv.cjcat.stardust.twoD.zones.SinglePoint;
	
	[SWF(backgroundColor = "#FFFFFF", frameRate = 60)]
	public class Main extends Sprite  {
		
		private var _bmpd:BitmapData;
		private var _bmp:Bitmap;
		private var _emitter:Emitter;
		private var _colorTransform:ColorTransform;
		private var _blur:BlurFilter;
		private var _mouseFollower:SinglePoint;
		
		public function Main() {
			_bmpd = new BitmapData(465, 465, true, 0xFFFFFFFF);
			_bmp = new Bitmap(_bmpd);
			addChild(_bmp);
			
			_emitter = new InkEmitter(_mouseFollower = new SinglePoint(mouseX, mouseY));
			_emitter.particleHandler = new InkHandler(_bmpd);
			addEventListener(Event.ENTER_FRAME, mainLoop);
			
			_colorTransform = new ColorTransform(1, 1, 1, 1, 2, 2, 2);
			_blur = new BlurFilter(2, 2, 1);
		}
		
		private var point:Point = new Point();
		private function mainLoop(e:Event = null):void {
			_mouseFollower.x = mouseX;
			_mouseFollower.y = mouseY;
			
			_bmpd.lock();
			_bmpd.applyFilter(_bmpd, _bmpd.rect, point, _blur);
			_bmpd.colorTransform(_bmpd.rect, _colorTransform);
			_emitter.step();
			_bmpd.unlock();
		}
	}
}

import flash.display.BitmapData;
import idv.cjcat.stardust.common.actions.Age;
import idv.cjcat.stardust.common.actions.DeathLife;
import idv.cjcat.stardust.common.actions.ScaleCurve;
import idv.cjcat.stardust.common.clocks.SteadyClock;
import idv.cjcat.stardust.common.handlers.ParticleHandler;
import idv.cjcat.stardust.common.initializers.Color;
import idv.cjcat.stardust.common.initializers.Life;
import idv.cjcat.stardust.common.initializers.Scale;
import idv.cjcat.stardust.common.math.UniformRandom;
import idv.cjcat.stardust.common.particles.Particle;
import idv.cjcat.stardust.twoD.actions.Damping;
import idv.cjcat.stardust.twoD.actions.Move;
import idv.cjcat.stardust.twoD.emitters.Emitter2D;
import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass;
import idv.cjcat.stardust.twoD.initializers.Position;
import idv.cjcat.stardust.twoD.initializers.Velocity;
import idv.cjcat.stardust.twoD.particles.Particle2D;
import idv.cjcat.stardust.twoD.zones.LazySectorZone;
import idv.cjcat.stardust.twoD.zones.SinglePoint;

class InkEmitter extends Emitter2D {
	
	public function InkEmitter(point:SinglePoint) {
		super(new SteadyClock(20));
		
		//initializers
		addInitializer(new Life(new UniformRandom(30, 10)));
		addInitializer(new Scale(new UniformRandom(1, 0.75)));
		addInitializer(new Position(point));
		addInitializer(new Velocity(new LazySectorZone(3, 1)));
		
		//actions
		addAction(new Age());
		addAction(new DeathLife());
		addAction(new Move());
		addAction(new Damping(0.1));
		addAction(new ScaleCurve(0, 40));
	}
}

class InkHandler extends ParticleHandler {
	
	private var _bmpd:BitmapData;
	
	public function InkHandler(bmpd:BitmapData) {
		_bmpd = bmpd;
	}
	
	private var _p2D:Particle2D;
	private var _ratio:Number;
	override public function readParticle(particle:Particle):void {
		_p2D = Particle2D(particle);
		_ratio = _p2D.life / _p2D.initLife;
		_bmpd.setPixel32(_p2D.x, _p2D.y, _ratio * 0xff << 24 | (_bmpd.getPixel32(_p2D.x, _p2D.y) & 0xFF000000));
	}
}